package com.pony.service.impl;

import com.google.code.kaptcha.Producer;
import com.pony.constant.MD5Constant;
import com.pony.constant.RedisConstant;
import com.pony.context.BaseContext;
import com.pony.dto.EmployeeLoginDTO;
import com.pony.entity.Employee;
import com.pony.enums.AppHttpCodeEnum;
import com.pony.mapper.EmployeeMapper;
import com.pony.result.R;
import com.pony.service.IEmployeeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pony.utils.BeanUtils;
import com.pony.utils.IpUtils;
import com.pony.utils.JwtUtils;
import com.pony.utils.MD5Utils;
import com.pony.vo.EmployeeInfoVO;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author pony
 * @since 2023-11-16
 */
@Service
@RequiredArgsConstructor
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {
    private final Producer captchaProducer;
    private final StringRedisTemplate redisTemplate;
    /**
     * 验证码接口-以流的形式写回验证码图片
     * @param request
     * @param response
     */
    @Override
    public void getVerifyCode(HttpServletRequest request, HttpServletResponse response) {
        //1、生成验证码的数字
        String verifyCode = captchaProducer.createText();
        //2、将验证码放到 redis 缓存里（设置过期时间120s）
        redisTemplate.opsForValue().set(getCaptchaKey(request), verifyCode, 120, TimeUnit.SECONDS);
        //3、生成验证码图片
        BufferedImage verifyCodeImage = captchaProducer.createImage(verifyCode);
        //4、将图片以流的形式写出去
        try {
            ServletOutputStream outputStream = response.getOutputStream();
            ImageIO.write(verifyCodeImage, "png", outputStream);
            outputStream.flush();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 登录
     * @param dto
     * @param request
     * @return
     */
    @Override
    public R login(EmployeeLoginDTO dto, HttpServletRequest request) {
        //0、判断验证码是否正确
        //获取 redis 中验证码的 key 值
        String captchaKey = getCaptchaKey(request);
        //根据 key 值取 验证码
        Object value = redisTemplate.opsForValue().get(captchaKey);
        if (value==null){
            return R.error(AppHttpCodeEnum.CODE_EXPIRE);
        }
        if (!dto.getVerifyCode().equals(value)){
            return R.error(AppHttpCodeEnum.CODE_ERROR);
        }
        //1、判断是否由此用户，根据账号查询数据库
        Employee employeeDB = lambdaQuery()
                .eq(Employee::getUsername, dto.getUsername())
                .one();
        //非空判断
        if (Objects.isNull(employeeDB)){
            return R.error(AppHttpCodeEnum.AUTHENTICATION_FAILED);
        }
        //2、判断密码是否正确
        String md5Password = MD5Utils.encodeWithSalt(dto.getPassword(), MD5Constant.SALT);
        if(!employeeDB.getPassword().equals(md5Password)){
            return R.error(AppHttpCodeEnum.AUTHENTICATION_FAILED);
        }
        //3、 密码正确，生成 token，返回前端
        String token = JwtUtils.getJwtToken(String.valueOf(employeeDB.getId()));
        return R.success().message("登录成功！").data("token", token);
    }

    /**
     * 根据id，查询单个员工信息
     * @return
     */
    @Override
    public R getEmployeeInfoById() {
        //1、获取员工id
        Long employeeId = BaseContext.getCurrentId();
        //2、查询数据库
        Employee employee = lambdaQuery()
                .eq(Employee::getId, employeeId)
                .one();
        //3、封装vo数据
        EmployeeInfoVO vo = BeanUtils.copyBean(employee, EmployeeInfoVO.class);
        return R.success().message("登录员工信息").data("employeeInfo", vo);
    }

    /**
     * 登出接口
     * @return
     */
    @Override
    public R logout() {
        //删除登录用户Id
        BaseContext.removeCurrentId();
        return  R.success().message("退出成功！");
    }


    /**
     * 验证码 存入redis缓存的 key 值
     * 通过 用户IP + 用户信息 加密后作为 key 值
     * @param request
     * @return
     */
    public String getCaptchaKey(HttpServletRequest request){
        //1、调用工具方法获取 ip
        String ip = IpUtils.getIpAddr(request);
        /*2、获取用户信息，User-Agent，网站服务器通过识别 “UA”来确定用户所使用
         的操作系统版本、CPU 类型、浏览器版本等信息。*/
        String userInfo = request.getHeader("User-Agent");
        //3、将 ip 和 用户信息 userInfo 加密作为 key
        String captchaKey = RedisConstant.VERIFY_CODE + DigestUtils.md5DigestAsHex((ip+userInfo).getBytes());
        //4、设置前缀并返回
        return captchaKey;
    }

}
